package ldh.im.fxbase.service;

import ldh.im.dto.business.item.ModuleInfoItem;
import ldh.im.dto.business.item.ModuleItemInfo;
import ldh.im.fxbase.dao.ImModuleDao;
import ldh.im.fxbase.dao.ImModuleItemDao;
import ldh.im.fxbase.data.pojo.ImModule;
import ldh.im.fxbase.data.pojo.ImModuleItem;
import ldh.im.fxbase.data.pojo.status.ImModuleItemStatus;
import ldh.im.fxbase.data.pojo.status.ImModuleItemType;
import ldh.im.fxbase.data.pojo.status.ImModuleStatus;
import ldh.im.fxbase.util.BeanFactory;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ModuleService {

    private ImModuleDao moduleDao = BeanFactory.getInstance().getBean(ImModuleDao.class);
    private ImModuleItemDao moduleItemDao = BeanFactory.getInstance().getBean(ImModuleItemDao.class);

    public void saveOrUpdates(String userId, List<ModuleInfoItem> moduleInfoItems) throws SQLException {
        if (moduleInfoItems.size() < 1) return;

        List<ImModule> imModuleList = moduleInfoItems.stream().map(cinfo->toModule(userId, cinfo)).collect(Collectors.toList());

        List<ImModule> insertImModuleList = new ArrayList<>();
        List<ImModule> updateImModuleList = new ArrayList<>();

        List<ImModuleItem> insertModuleItemList = new ArrayList();
        List<ImModuleItem> updateModuleItemList = new ArrayList();

        for(ImModule imModule : imModuleList) {
            ImModule dbModule = moduleDao.getByName(imModule.getName());
            if (dbModule == null) {
                insertImModuleList.add(imModule);
                insertModuleItemList.addAll(imModule.getModuleItemList());
            } else {
                imModule.setId(dbModule.getId());
                updateImModuleList.add(imModule);

                for (ImModuleItem moduleItem : imModule.getModuleItemList()) {
                    ImModuleItem dbModuleItem = moduleItemDao.getByModuleIdAndName(dbModule.getId(), moduleItem.getName());
                    if (dbModuleItem == null) {
                        moduleItem.setModuleId(imModule.getId());
                        insertModuleItemList.add(moduleItem);
                    } else {
                        moduleItem.setId(dbModuleItem.getId());
                        updateModuleItemList.add(moduleItem);
                    }
                }
            }
        }

        if (insertImModuleList.size() > 0) {
            moduleDao.batchInserts(insertImModuleList);
            insertImModuleList.forEach(module-> {
                if (module.getModuleItemList() != null) {
                    module.getModuleItemList().forEach((moduleItem)->{
                        moduleItem.setModuleId(module.getId());
                    });
                }
            });
        }
        if (updateImModuleList.size() > 0) {
            moduleDao.batchUpdates(updateImModuleList);
        }

        if (insertModuleItemList.size() > 0) {
            moduleItemDao.batchInserts(insertModuleItemList);
        }
        if (updateModuleItemList.size() > 0) {
            moduleItemDao.batchUpdates(updateModuleItemList);
        }
    }

    public void update(ImModule module) throws SQLException {
        moduleDao.batchUpdates(Arrays.asList(module));
    }

    public void saveOrUpdate(ImModule historyModule) throws SQLException {
        ImModule dbModule =  moduleDao.getByName(historyModule.getName());
        if (dbModule == null) {
            moduleDao.batchInserts(Arrays.asList(historyModule));
            if (historyModule.getModuleItemList() != null) {
                historyModule.getModuleItemList().forEach((moduleItem)->moduleItem.setModuleId(historyModule.getId()));
                moduleItemDao.batchInserts(historyModule.getModuleItemList());
            }
        } else {
            for (ImModuleItem moduleItem : historyModule.getModuleItemList()) {
                moduleItem.setModuleId(dbModule.getId());
                ImModuleItem dbModuleItem =  moduleItemDao.getByModuleIdAndName(dbModule.getId(), moduleItem.getName());
                if (dbModuleItem != null) {
                    moduleItemDao.batchUpdates(Arrays.asList(moduleItem));
                } else {
                    moduleItemDao.batchInserts(Arrays.asList(moduleItem));
                }
            }
        }
    }

    public List<ImModule> getModules() throws SQLException {
        List<ImModule> dbModules = moduleDao.getAll();
        dbModules = dbModules.stream().filter((module)->!module.getName().contains("_history")).collect(Collectors.toList());
        for(ImModule module : dbModules) {
            List<ImModuleItem> moduleItems = moduleItemDao.getByModuleId(module.getId());
            module.setModuleItemList(moduleItems);
        }
        return dbModules;
    }

    public ImModule getHistoryModule(String userId) throws Exception {
        ImModule module = moduleDao.getByName(userId + "_history");
        if (module != null) {
            List<ImModuleItem> moduleItems = moduleItemDao.getByModuleId(module.getId());
            if (moduleItems.size() > 4) {
                moduleItems = moduleItems.subList(0, 4);
            }
            List<ImModuleItem> newImModuleItems = new ArrayList();
            for (ImModuleItem moduleItem : moduleItems) {
                int firstIndex = moduleItem.getName().indexOf("_");
                String moduleIdStr = moduleItem.getName().substring(0, firstIndex);
                String moduleItemName = moduleItem.getName().substring(firstIndex+1);
                ImModuleItem dbModuleItem =  moduleItemDao.getByModuleIdAndName(Long.parseLong(moduleIdStr), moduleItemName);
                newImModuleItems.add(dbModuleItem);
            }
            module.setModuleItemList(newImModuleItems);
        }
        return module;
    }

    private ImModule toModule(String userId, ModuleInfoItem cinfo) {
        ImModule module = new ImModule();
        module.setName(cinfo.getName());
        module.setDescription(cinfo.getDescription());
        module.setNo(cinfo.getNo());
        module.setStatus(ImModuleStatus.wrap(cinfo.getStatus()));

        module.setModuleItemList(toModuleItems(cinfo));
        return module;
    }

    private ImModuleItem toModuleItem(ModuleItemInfo moduleItemInfo) {
        ImModuleItem moduleItem = new ImModuleItem();
        moduleItem.setName(moduleItemInfo.getName());
        moduleItem.setDescription(moduleItemInfo.getDescription());
        moduleItem.setIcon(moduleItemInfo.getIcon());
        moduleItem.setParams(moduleItemInfo.getParams());
        moduleItem.setUrl(moduleItemInfo.getUrl());
        moduleItem.setNo(moduleItemInfo.getNo());
        moduleItem.setType(ImModuleItemType.wrap(moduleItemInfo.getType()));
        moduleItem.setStatus(ImModuleItemStatus.wrap(moduleItemInfo.getStatus()));
        return moduleItem;
    }

    private List<ImModuleItem> toModuleItems(ModuleInfoItem cinfo) {
        List<ImModuleItem> result = new ArrayList<>();
        if (cinfo.getModuleItemInfoList() != null) {
            List<ImModuleItem> moduleItems = cinfo.getModuleItemInfoList().stream().map(this::toModuleItem).collect(Collectors.toList());
            result.addAll(moduleItems);
        }
        return result;
    }
}
